﻿/*
引用计数的本质：一块资源有多少个智能指针对象管理
	shared_ptr，引用计数的设计，主要这里一份资源就需要一个引用计数，所以引用计数用静态成员的方式是无法实现的，
	要使用堆上动态开辟的方式，构造智能指针对象时来一份资源，就要new一个引用计数出来。多个shared_ptr指向资源时
	就++引用计数，shared_ptr对象析构时就--引用计数，引用计数减到0时代表当前析构的shared_ptr是最后一个管理资源的
	对象，则析构资源。



	智能指针析构时默认是进行delete释放资源，这也就意味着如果不是new出来的资源，交给智能指
	针管理，析构时就会崩溃。智能指针支持(在构造时给一个删除器)，所谓删除器本质就是一个可调用
	对象，这个可调用对象中实现你想要的释放资源的方式，当构造智能指针时，给了定制的删除器（调用的方式），
	在智能指针析构时就会调用删除器去释放资源。因为new[]经常使用，所以为了简洁一点，
	unique_ptr和shared_ptr 都特化了一份[]的版本，使用时 unique_ptr<Date[]> up1(new Date[5]);
	shared_ptr<Date[]> sp1(new Date[5]); 就可以管理new[]的资源。
	(也就是说：删除器可以是函数指针，可以是仿函数，可以是lambda，可以是包装器     都是可调用对象)

	template<class U,class D> shared_ptr (U* p,D del);
	析构的时候会调用：del(_ptr)

	删除器可以解决一切问题




shared_ptr 和 weak_ptr
shared_ptr
	  shared_ptr大多数情况下管理资源非常合适，支持RAII，也支持拷贝。但是在循环引用的场景下会
	  导致资源没得到释放内存泄漏，所以要认识循环引用的场景和资源没释放的原因，使用weak_ptr
	  解决这种问题。

循环引用的weak_ptr很重要

weak_ptr
	1.weak_ptr不支持RAII，也不支持访问资源，所以我们看文档发现weak_ptr构造时不支持绑定到资
	  源，只支持绑定到shared_ptr，绑定到shared_ptr时，不增加shared_ptr的引用计数，那么就可以
	  解决上述的循环引用问题。
	2.weak_ptr也没有重载operator* 和operator-> 等，因为他不参与资源管理，那么如果他绑定的
	  shared_ptr已经释放了资源，那么他去访问资源就是很危险的。weak_ptr支持 expired 检查指向的
	  资源是否过期，use_count也可获取shared_ptr 的引用计数，weak_ptr想访问资源时，可以调用lock
	  返回一个管理资源的shared_ptr，如果资源已经被释放，返回的shared_ptr是一个空对象，如
	  果资源没有释放，则通过返回的shared_ptr访问资源是安全的。

weak_ptr 也有引用计数     会指向引用计数

shared_ptr是线程安全的   引用计数是线程安全的    智能指针本身是线程安全的，但是指向的资源不是
	


内存泄漏
	什么是内存泄漏：内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存，一般是忘记释
	放或者发生异常释放程序未能执行导致的。内存泄漏并不是指内存在物理上的消失，而是应用程序分
	配某段内存后，因为设计错误，失去了对该段内存的控制，因而造成了内存的浪费。

	内存泄漏的危害：普通程序运行一会就结束了出现内存泄漏问题也不大，进程正常结束，页表的映射
	关系解除，物理内存也可以释放。⻓期运行的程序出现内存泄漏，影响很大，如操作系统、后台服
	务、长时间运行的客户端等等，不断出现内存泄漏会导致可用内存不断变少，各种功能响应越来越
	慢，最终卡死。


如何避免内存泄漏
	1.工程前期良好的设计规范，养成良好的编码规范，申请的内存空间记着匹配的去释放。
	  ps：这个理想状态。但是如果碰上异常时，就算注意释放了，还是可能会出问题。需
	  要下一条智能指针来管理才有保证。
	2.尽量使用智能指针来管理资源，如果自己场景比较特殊，采用RAII思想自己造个轮子管理。
	3.定期使用内存泄漏工具检测，尤其是每次项目 快上线前，不过有些工具不够靠谱，或者是收费。
	4.总结一下：内存泄漏非常常⻅，解决方案分为两种：
	  *  事前预防型。如智能指针等。   
	  *  事后查错型。如泄漏检测工具。

*/